/*
	Copyright (c) 2009, SpLib.net
  	All rights reserved.
  	
  	Author:6spring
  	About:网络消息包
*/

package SpLib.Net
{	
	import SpLib.Tools.CRC32;
	
	import com.adobe.serialization.json.JSON;
	import com.hurlant.crypto.Crypto;
	import com.hurlant.crypto.symmetric.ICipher;
	import com.hurlant.util.Base64;
	
	import flash.utils.ByteArray;
	import flash.utils.Endian;
	
	public class NetPak
	{
		public static const HAND_HEADER:String = "json:connect.";
		public static const PAK_HEADER:String = "msg.";
		public static const PAK_TAIL:String = ".end";	
		public static const MAX_CACHE_NUM:int = 256;
			
		public var m_nKey:uint;						//消息校验码
		public var m_nFrameNum:int;					//帧号
		public var m_Msg:SpLib.Net.NetMsg = null;	//消息内容
		public var m_sDataStr:String = "";
		
		public function NetPak()
		{
			m_nKey = 0;
		}
		
		public function GetAsJson():Object
		{
			m_Msg.MakeKey();
	
			var obj:Object = new Object;
			obj.f = m_nFrameNum;
			obj.t = m_Msg.m_nMsgtype;
			obj.e = m_Msg.m_nEveID;
			if(m_Msg.m_Address!=null)
			{
				obj.a = m_Msg.m_Address.GetAsArray();
			}
			
			if(m_Msg.m_Value!=null)
			{
				obj.v = m_Msg.m_Value;
			}
			
			return obj;
		}
		
		public function SetAsJson(obj:Object):Boolean
		{
			if( !obj.hasOwnProperty("f") ||
				!obj.hasOwnProperty("t") ||
				!obj.hasOwnProperty("e"))
				{
					return false;
				}
			
			m_nFrameNum = obj.f;
			
			if(m_Msg==null)
			{
				m_Msg = new SpLib.Net.NetMsg();
			}
			
			m_Msg.m_nMsgtype = obj.t;
			m_Msg.m_nEveID = obj.e;
			
			if(obj.hasOwnProperty("a"))
			{
				m_Msg.m_Address.SetAsArray(obj.a);
			}
			
			if(obj.hasOwnProperty("v"))
			{
				m_Msg.m_Value = obj.v;
			}
			
			return true;
		}
		
		public function toString():String
		{
			if(m_sDataStr==null || m_sDataStr.length==0)
			{
				m_sDataStr = JSON.encode(GetAsJson());
			}
					
			return m_sDataStr;
		}
		
		private function GetEncryptKey(pwd:int):ByteArray
		{
			var key:ByteArray = new ByteArray;
			key.endian = flash.utils.Endian.LITTLE_ENDIAN;
			key.writeInt(pwd);
					
			//服务器端约定，密钥为int时，均把剩余位以0填满
			var i:int;
			for(i=0;i<7;i++)
			{
				key.writeInt(0);
			}
			
			return key;
		}
		
		public function GetSendStr(basekey:uint,charset:String,encrypt:Boolean=false,base64:Boolean = false,zip:Boolean = false):String
		{
			m_sDataStr = "";		
			m_nKey = SpLib.Tools.CRC32.MakeStr(basekey,toString(),charset);
			
			//不做任何加密措施
			if(!encrypt && !base64 && !zip)
			{
				return PAK_HEADER + "{\"k\":" + m_nKey.toString() + ",\"z\":0,\"d\":" + toString() + "}" + PAK_TAIL;
			}
			
			//加密应用
			var databytes:ByteArray = new ByteArray;
			databytes.writeMultiByte(toString(),charset);
			databytes.position = 0;
			
			var ziped:Boolean = false;
			if(zip && databytes.length>=256)
			{
				databytes.compress();
				databytes.position = 0;
				ziped = true;
			}
			
			if(encrypt)
			{
				//采用aes-ecb方式加密，尾块pkcs5方式填充
				var des3:ICipher = com.hurlant.crypto.Crypto.getCipher("aes-ecb",GetEncryptKey(m_nKey),com.hurlant.crypto.Crypto.getPad("pkcs5"));
				des3.encrypt(databytes);
			}
			
			//为了协议兼容，目前只要压缩或加密，必定转换为base64
			var datastr:String;
			if(base64)
			{
				datastr = "\"" + com.hurlant.util.Base64.encodeByteArray(databytes) + "\"";
			}
			else
			{
				datastr = databytes.readMultiByte(databytes.length,charset);
			}
			
			var str:String = PAK_HEADER + "{\"k\":" + m_nKey.toString() + ",\"z\":" ;
			if(ziped)
			{
				str += "1";
			}
			else
			{
				str +="0";
			}
			
			str+= ",\"d\":" + datastr + "}" + PAK_TAIL;
			return str;
		}
		
		public function SetAsPakStr(pwd:int,str:String,charset:String,encrypt:Boolean,zip:Boolean):Boolean
		{
			var databytes:ByteArray = com.hurlant.util.Base64.decodeToByteArray(str);
					
			//解密
			if(encrypt)
			{
				var des3:ICipher = com.hurlant.crypto.Crypto.getCipher("aes-ecb",GetEncryptKey(pwd),com.hurlant.crypto.Crypto.getPad("pkcs5"));
				des3.decrypt(databytes);
			}
				
			databytes.position = 0;
			var datastr:String;
			if(!zip)
			{
				datastr = databytes.readMultiByte(databytes.length,charset);
			}
			else
			{
				databytes.uncompress();
				databytes.position = 0;
				datastr = databytes.readMultiByte(databytes.length,charset);
			}
			
			//解析
			var obj:Object = JSON.decode(datastr);
			if(obj!=null)
			{
				return SetAsJson(obj);
			}
			
			return false;	
		}
		
	}
}